package com.behome.netty.netty_B.bean;


import com.behome.netty.common.ByteConventerKit;
import com.behome.netty.common.util.CRCKit;
import lombok.Data;
import lombok.extern.slf4j.Slf4j;

import java.nio.ByteBuffer;

@Data
@Slf4j
public class ReBackPacket {

    public static final int MIN_LENGTH = 32;
    protected ReBackPacketHead head;
    protected ReBackPacketBody body;
    protected ReBackPacketTail tail;

    public ReBackPacket() {
    }

    public byte[] serialize() {
        byte[] bodyData = this.body.serialize();
        byte[] headData = this.head.serialize();
        if (this.tail == null) {
            tail = new ReBackPacketTail(this.head, this.body);
        }
        byte[] tailData = this.tail.serialize();
        ByteBuffer byteBuffer = ByteBuffer.allocate(bodyData.length + headData.length + tailData.length);
        byteBuffer.put(headData).put(bodyData).put(tailData);
        return byteBuffer.array();
    }

    public static ReBackPacket deserialize(byte[] data) {
        ReBackPacket ret = new ReBackPacket();
        if (data != null && data.length > 0) {
            if (crcValidate(data)) {
                ByteBuffer byteBuffer = ByteBuffer.wrap(data);
                byte[] headData = new byte[11];
                byteBuffer.get(headData);
                ReBackPacketHead head = ReBackPacketHead.deserialize(headData);
                short packetLength = byteBuffer.getShort(9);
                int bodyLength = packetLength - 11 - 4;
                byte[] bodyData = new byte[bodyLength];
                byteBuffer.position(11);
                byteBuffer.get(bodyData);
                ReBackPacketBody body = null;
                try {
                    body = ReBackPacketBody.deserialize(bodyData);
                } catch (Exception e) {
                    log.error("发生异常", e);
                }
                ret.setHead(head);
                ret.setBody(body);
            }else{
                log.error("CRC32校验错误!");
            }
        }

        return ret;
    }

    private static boolean crcValidate(byte[] data) {
        byte[] pkg = new byte[data.length - 4];
        System.arraycopy(data, 0, pkg, 0, pkg.length);
        byte[] crc32ValData = new byte[4];
        System.arraycopy(data, data.length - 4, crc32ValData, 0, crc32ValData.length);
        int crcCalcVal = CRCKit.crc32Calc(pkg);
        int crcVal = ByteConventerKit.bytesToInt2(crc32ValData, 0);
        boolean ret = crcCalcVal == crcVal;
        if (!ret) {
            System.out.println("CRC32校验错误(计算值为" + crcCalcVal + ",待校验值为" + crcVal + ").");
        }

        return ret;
    }

    public String toString() {
        if (this.head != null && this.body != null) {
            String sourceCode = this.body.getSourceCode();
            int head = this.head.getSessionId();
            BusinessReBackBase businessReBack = this.body.getBusinessReBack();
            String cmdInfo = "空";
            if(businessReBack !=null){
                cmdInfo = businessReBack.toString();
            }
            return "回传指令(sourceCode:" + sourceCode + ",sessionId:" + head + ",cmdInfo:" + cmdInfo;
        } else {
            return null;
        }
    }

}
